/**
 * Created by xc on 17/01/09.
 */
var ItbItemsModel = require('../../../common/mysql/mapping/ItbItemsModel');
var TgUserDocModel = require('../../../common/mysql/mapping/TgUserDocModel');
var ItbTradeOrderModel = require('../../../common/mysql/mapping/ItbTradeOrderModel');
var ItbTradeOrderDetailModel = require('../../../common/mysql/mapping/ItbTradeOrderDetailModel');
var ItbTmplPriceModel = require('../../../common/mysql/mapping/ItbTmplPriceModel');
var ItbBuyTmplModel = require('../../../common/mysql/mapping/ItbBuyTmplModel');
var ItbTradeStateHisModel = require('../../../common/mysql/mapping/ItbTradeStateHisModel');
var ItbInvoiceModel = require('../../../common/mysql/mapping/ItbInvoiceModel');
var ItbPaymentHisModel = require('../../../common/mysql/mapping/ItbPaymentHisModel');
var ItbAddressModel = require('../../../common/mysql/mapping/ItbAddressModel');
var ItbCouponModel = require('../../../common/mysql/mapping/ItbCouponModel');
var ItbMemberModel = require('../../../common/mysql/mapping/ItbMemberModel');
var ItbActivityRModel = require('../../../common/mysql/mapping/ItbActivityRModel');
var CommonUtil = require('../../../common/util/CommonUtil');
var CONFIG = require('../../../common/config');
var moment = require('moment');  // 日期格式化

var luaUtil = require('./luaUtil');
var superagent = require('superagent');//  使用了superagent来发送请求
var Alipay = require('alipay-node-sdk');

var request = require('request');
var xml2js = require('xml2js');
var async = require('async');
var crypto = require('crypto');
var path = require('path');

//--------------------------------------------------------------------------------------------
// 网站和APP用 (对应开放平台)
var ITB_WX_INFO = {
    APPID: 'wxb6504bf6ff28cb10',// APP的APPID(微信开放平台审核通过的应用APPID)
    MCH_ID: '1419473302',// 商户ID
    KEY: 'Wefub8730xfyFekodbfgoFQmmnOwEREp',// ［key为在微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置］
};

// H5用 (对应公众平台:一键生成创业板)
var ITB_WX_INFO_2 = {
    APPID: 'wx3d505dd750d82e65',// 公众号的APPID
    MCH_ID: '1427545102',// 商户ID
    KEY: 'Eefub3556xfyFekDEbfgoETmmnOw22Ep',// 在商户平台手动生成
};

var optionsForAliPay = {
    appId: '2018041602565700',
    rsaPrivate: path.resolve(__dirname, '../../yjsc/ext/alipay_yjsc_private_key.pem'),
    rsaPublic: path.resolve(__dirname, '../../yjsc/ext/alipay_yjsc_ali_public_key.pem'),
    sandbox: false,
    signType: 'RSA2',
    notifyUrl: 'https://paycb.itbour.com:818/payment/chkAlipayNotify'   // 正式支付回调
};
/*
* 切记:
* 1. 官方未提供 nodejs sdk, 此处使用 alipay-node-sdk 是自行签名操作, 使用签名时一定使用第二种生成方式, 官方提供工具有问题
* 2. 阿里公钥是 txt 形式, 转 pem 格式, 添加 begin 头 end 尾, 每64字符换行,
* */
var yjscAlipayClient = new Alipay(optionsForAliPay);

//--------------------------------------------------------------------------------------------
var payUtil = (function () {
    function payUtil() {
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 返回json
     */
    payUtil.ret_func_json = function (success, msg, data, res){
        var obj = {
            success: success,
            msg: msg,
            data: data
        };
        // 返回
        res.set('Content-Type', 'application/json');
        res.json(obj);
    };

    //--------------------------------------------------------------------------------------------
    /* 创建各种类型的订单编号
     * 参数 device:  0表示从pc来的请求/1表示ios/2表示android/...
     * 参数 orderType:  商品订单:10  发票订单:20  模版订单:30  虚拟商品订单:40  秒杀订单:50
     * 参数 callback:  回调,参数如下:
     *          error: 错误消息
     *          order_no: 订单编号
     */
    // 4：pc,5：ios,6：android,7: h5,8: 小程序，9: app嵌入h5
    payUtil.DEVICE_ID_MAP ={"0":4,"1":5,"2":6,"3":9,"4":4,"5":7,"201":7,"301":7};
    payUtil.DEVICE_P01_FLAG_MAP ={
        "10":CONFIG.ORDER_TYPE_ORDER,
        "20":CONFIG.ORDER_TYPE_INVOICE,
        "30":CONFIG.ORDER_TYPE_TEMPLATE,
        "40":CONFIG.ORDER_TYPE_VIP,
        "50":CONFIG.ORDER_TYPE_SECKILL
    };
    payUtil.createOrderNo = function(device, orderType){
        var cur = CommonUtil.genCurYearDayTimeStr();
        var p00 = payUtil.DEVICE_ID_MAP[device] || 0;// 标志
        var p01 = payUtil.DEVICE_P01_FLAG_MAP[orderType] ||0; // 订单类型
        var p0 = p00+""+p01;
        var p1 = cur.substr(8); // 分秒
        var p2 = CommonUtil.randomNumStr(3); // 3位随机数
        var p3 = cur.substr(0,8);// 年月日时
        p3 = CommonUtil.yearDayTimeStrtoAlphabet(p3); // 4位26进制字符串
        var ret = CommonUtil.mix(p0+p1+p2, p3);
        return ret;
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 生成随机字符串
     * @param len: 字符串长度(默认32位)
     * @param flg: 1:纯数字; 2:纯字母; 其他(默认):数字+字母
     * @returns {string}
     */
    payUtil.genNonceStr = function(len,flg){
        var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        if(flg == 1) {
            chars = '0123456789';
        } else if(flg == 2) {
            chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
        }
        var maxPos = chars.length;
        var ret = "";
        var size = Number(len||'32');
        for(var i = 0; i < size; i++) {
            ret += chars.charAt(Math.floor(Math.random() * maxPos));
        }
        return ret;
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 拼接参数字符串(eg: key1=value1&key2=value2…)
     * ◆ 参数名ASCII码从小到大排序（字典序）
     * ◆ 如果参数的值为空不参与签名
     * ◆ 参数名区分大小写
     * @param args: 字典对象
     * @returns {string}
     */
    payUtil.toWxParamStr = function(args) {
        var keys = Object.keys(args);
        keys = keys.sort();
        var newArgs = {};
        keys.forEach(function (key) {
            if(args[key]!=null && (args[key]+'')!='') {// 过滤空值项
                //newArgs[key.toLowerCase()] = args[key];
                newArgs[key] = args[key];// 签名时候的参数不需要转换为小写的
            }
        });
        var string = '';
        for (var k in newArgs) {
            string += '&' + k + '=' + newArgs[k];
        }
        string = string.substr(1);
        return string;
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 计算[微信支付]签名
     * @param key: 密钥
     * @param param: 参数
     * @returns {string}
     */
    payUtil.calcWxPaySign = function(key, param) {
        var paramObj = param||{};
        var paramStr = payUtil.toWxParamStr(paramObj);

        key = key || ITB_WX_INFO.KEY;

        paramStr = paramStr + '&key='+key;
        console.log("CalcParam: "+paramStr);
        var sign = crypto.createHash('md5').update(paramStr,'utf8').digest('hex');
        sign = sign.toUpperCase();
        console.log("CalcSign: "+sign);
        return sign;
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 获取xml节点数据
     * @param node_name: 节点名称
     * @param xml: xml字符串
     * @returns {string}
     */
    payUtil.getXMLNodeValue = function(node_name,xml){
        var ret = null;
        var tmp = xml.split("<"+node_name+">");
        var tmp2 = null;
        if(tmp && tmp.length>1){
            tmp2 = tmp[1].split("</"+node_name+">");
        }
        if(tmp2 && tmp.length>0){
            ret = tmp2[0];
        }
        return ret;
    };

    //------------------------------------------------------------------
    /**
     * 调用微信支付[统一下单]API
     * 参数 key: 密钥
     * 参数 formData: XML格式参数
     */
    payUtil.reqWxApi_payUniOrd = function(key, formData, cb) {
        var url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        request({url:url,method:'POST',body: formData},function(err,response,retBody){
            if(!err && response.statusCode == 200){
                console.log(retBody);
                //var prepay_id = getXMLNodeValue('prepay_id', retBody.toString("utf-8"));
                //if(prepay_id) {
                //  var tmp = prepay_id.split('[');
                //  var tmp2 = tmp[2].split(']');
                //  var prepayId = tmp2[0];
                //}

                var parser = new xml2js.Parser({ trim:true, explicitArray:false, explicitRoot:false });
                parser.parseString((retBody||'').toString("utf-8"), function(parseErr, parseRet){
                    if(parseErr) {
                        console.log('payUtil.js [reqWxApi] parser xml Err: '+parseErr);
                        return cb(parseErr, null);
                    }

                    // 验证返回值签名
                    var retSign = parseRet.sign||'';
                    if(parseRet.sign){
                        delete parseRet.sign;
                    }
                    var calSign = payUtil.calcWxPaySign(key, parseRet);

                    console.log('retSign:[' + retSign + '] calSign:[' + calSign + ']');
                    if (!retSign || !calSign || retSign.toUpperCase() != calSign.toUpperCase()) {
                        return cb('[微信统一下单]返回数据非法', null);
                    }

                    // [return_code] 此字段是通信标识，非交易标识，交易是否成功需要查看result_code来判断
                    if((parseRet.return_code||'')=='SUCCESS') {

                        // 以下字段在return_code 和result_code都为SUCCESS的时候有返回:
                        // [trade_type]: 交易类型(调用接口提交的交易类型，取值如下：JSAPI，NATIVE，APP)
                        // [prepay_id]: 预支付交易会话标识,(微信生成的预支付回话标识，用于后续接口调用中使用，该值有效期为2小时)
                        if((parseRet.result_code||'')=='SUCCESS') {
                            parseRet.sign = retSign;
                            return cb(null, parseRet);
                        } else {
                            return cb(parseRet.err_code||'[微信统一下单]交易失败', null);
                        }

                    } else {
                        return cb(parseRet.return_msg||'[微信统一下单]通信失败', null);
                    }
                });
            } else {
                return cb(err, null);
            }
        });
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 调用微信支付[统一下单]API (APP支付用)
     * @param userId
     * @param openId (微信H5支付用)
     * @param tradeObjId: order_id 或 inv_id
     * @param type: 商品订单:10, 发票订单:20, 虚拟商品:40
     * @param callback
     *  {
     *      "prepayId": 1234567,
     *      "nonceStr": "qwertyuiopsdfghjkl",
     *      "timeStamp": 999990909090,
     *      "sign": "QWKSJDFHGJHDFHHDHH"
     *   }
     */
    payUtil.getUnifiedOrder = function(device, userId, openId, tradeObjId, type, callback) {

        var H5PayFlg = false;
        if(device == '5' || device == '201' || device == '301') {// 微信内嵌H5支付
            H5PayFlg = true;
        }

        // Parameter
        var timeStamp = Math.floor(Date.now()/1000)+"";// 时间戳

        var trade_type = "APP";// 交易类型(必填): APP/JSAPI/NATIVE(会返回code_url)
        var openid = openId || "";

        // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数
        // 支付成功后微信服务器通过POST请求通知这个地址
        var notify_url = 'https://paycb.itbour.com:818/payment/chkWxPayNotify';
        if(CONFIG.DEBUG) {
            notify_url = 'http://paycb.itbour.com/payment/chkWxPayNotify';
        }
        var appid = ITB_WX_INFO.APPID;// 应用ID(必填)
        var mch_id = ITB_WX_INFO.MCH_ID;// 商户号(必填)
        var key = ITB_WX_INFO.KEY;

        if(H5PayFlg) {// 内嵌H5支付
            trade_type = 'JSAPI';
            appid = ITB_WX_INFO_2.APPID;
            mch_id = ITB_WX_INFO_2.MCH_ID;
            key = ITB_WX_INFO_2.KEY;
            notify_url = 'https://paycb.itbour.com:818/payment/chkWxPayNotify2';
            if(CONFIG.DEBUG) {
                notify_url = 'http://paycb.itbour.com/payment/chkWxPayNotify2';
            }
        }

        // 附加数据: 暂定纪录userId,tradeObjId,type
        var attach = JSON.stringify({
            uid: userId||0, id: tradeObjId||0, type: type||0
        });
        var body = "示界港微信支付订单";// 商品或支付单简要描述 TODO

        var nonce_str = payUtil.genNonceStr(32);// 随机字符串,不长于32位(必填)

        var ip = "127.0.0.1";// 终端IP(必填) TODO

        var paramForSign = {
            appid: appid,
            attach: attach,
            body: body,
            mch_id: mch_id,
            nonce_str: nonce_str,
            notify_url: notify_url,
            openid: openid,
            out_trade_no: '',// 商户订单号(必填)
            spbill_create_ip: ip,
            total_fee: 0,// 总金额(必填)
            trade_type: trade_type,
        };

        // 获取订单信息
        if(type == 10 || type == 20 || type == 40 || type == 50) {
            var orderEnt = null;

            if(type == 10 || type == 40 || type == 50) {// 商品订单
                orderEnt = new ItbTradeOrderModel({
                    order_id: tradeObjId,
                    del_flg: 0
                });
            } else if(type == 20){// 发票订单
                orderEnt = new ItbInvoiceModel({
                    inv_id: tradeObjId,
                    del_flg: 0
                });
            }
            orderEnt.findFromDB(function(error, data){
                if(data && data.length>0){

                    var curState = Number(data[0].state || '0');
                    if(curState == 11) {
                        return callback('该订单已支付成功，无需重复支付！', null);
                    } else if(curState == 50) {
                        return callback('该订单因超时已取消，请重新下单！', null);
                    }

                    paramForSign.out_trade_no = '';
                    if(type == 10 || type == 40 || type == 50) {
                        paramForSign.out_trade_no = data[0].order_no;
                        paramForSign.total_fee = data[0].total_fee || 0;// 商品订单总金额
                    } else if(type == 20) {
                        paramForSign.out_trade_no = data[0].inv_no;
                        paramForSign.total_fee = data[0].mail_fee || 0;// 发票只算邮费
                    }

                    // 先统一更新为支付失败
                    payUtil.updOrderState(tradeObjId, type, 12, paramForSign.total_fee, userId,
                        function(updErr, updRet){
                            if (updErr) {
                                console.log("payUtil.js [getUnifiedOrder] Upd State(12) Err: " + updErr);
                                return callback(updErr, null);
                            }

                            // 开始支付
                            if(paramForSign.total_fee == 0) {// 免费不用支付
                                // 添加支付历史纪录
                                var insEnt = new ItbPaymentHisModel({
                                    type: type||0,
                                    trade_obj_id: tradeObjId||0,
                                    trade_obj_no: paramForSign.out_trade_no||0,
                                    state: 11,
                                    pay_platform: 0,// 无
                                    desc: 'SUCCESS',
                                    update_by: userId||0
                                });
                                insEnt.saveToDB(function(insErr, newHisId) {
                                    if(insErr) {
                                        console.log("payUtil.js [getUnifiedOrder] Ins PayHis Err: " + insErr);
                                    }

                                    payUtil.updOrderState(tradeObjId, type, 11, 0, userId, function(updErr2, updRet2){
                                        if(updErr2) {
                                            return callback(updErr2, null);
                                        }

                                        console.log("payUtil.js [getUnifiedOrder] Upd fee=0 Order ");

                                        // added 2017-06-14
                                        if(type==10) {
                                            // 尝试拆分支付成功的商品订单
                                            payUtil.splitTradeOrder_v5_5(tradeObjId, userId, function(procErr, procRet){
                                                if(procErr) {
                                                    console.log("payUtil.js [getUnifiedOrder] splitTradeOrder_v5_5 Err: "+procErr);
                                                }

                                                return  callback(updErr2, updRet2);
                                            });

                                        } else if(type==40) {
                                            // 虚拟商品特殊处理: 支付成功时直接[完成]
                                            payUtil.updOrderState(tradeObjId, type, 40, 0, userId, function(updErr3, updRet3){

                                                    // 更新vip会员信息
                                                    payUtil.updVipExpiryInfo(userId, tradeObjId, function(updErr4, updRet4){
                                                        return callback(updErr4, updRet4);
                                                    });
                                                }
                                            );

                                        } else if (type == 50){
                                            // 获取秒杀商品
                                            (new ItbTradeOrderModel).getSeckillOrderItemInfo(tradeObjId, function(getErr, getRet){
                                                if(getErr) {
                                                    return callback(getErr, null);
                                                }
                                                if(getRet && getRet.r_id) {

                                                    // 更新锁定商品状态
                                                    luaUtil.updLockActItemSuccess(getRet.r_id, userId, function(procErr, procRet){
                                                        if(procErr) {
                                                            return callback(procErr, null);// 更新失败直接返回
                                                        }

                                                        console.log('payUtil.js [getUnifiedOrder] updLockActItemSuccess Ret: '+procRet);
                                                        if(procRet!=0) {// 0表示成功，1表示不存在场次或商品，2表示用户未加锁
                                                            // 更新锁失败
                                                            return callback('Upd rds lock success NG',null);
                                                        }

                                                        // 秒杀订单: 支付成功时直接[完成]
                                                        payUtil.updOrderState(tradeObjId, type, 40, 0, userId, function(updErr3, updRet3){

                                                                // 创建真正的商品订单
                                                                payUtil.createSeckillRealItemOrder_v6_1(userId, tradeObjId, function(procErr, procRet){
                                                                    return callback(procErr, procRet);
                                                                });
                                                            }
                                                        );
                                                    });
                                                } else {
                                                    return callback('无效订单', null);
                                                }
                                            });


                                        } else {
                                            return  callback(updErr2, updRet2);
                                        }
                                    });
                                });

                            } else {// 需要支付
                                // 调用微信下单接口
                                var formData  = "<xml>";
                                formData  += "<appid>"+paramForSign.appid+"</appid>";  // 应用ID(必填)
                                formData  += "<attach>"+paramForSign.attach+"</attach>"; // 附加数据
                                formData  += "<body>"+paramForSign.body+"</body>";// 商品或支付单简要描述
                                formData  += "<mch_id>"+paramForSign.mch_id+"</mch_id>";// 商户号(必填)
                                formData  += "<nonce_str>"+paramForSign.nonce_str+"</nonce_str>";// 随机字符串,不长于32位(必填)
                                formData  += "<notify_url>"+paramForSign.notify_url+"</notify_url>";// 通知地址(必填)
                                formData  += "<openid>"+paramForSign.openid+"</openid>";
                                formData  += "<out_trade_no>"+paramForSign.out_trade_no+"</out_trade_no>";// 商户订单号(必填)
                                formData  += "<spbill_create_ip>"+paramForSign.spbill_create_ip+"</spbill_create_ip>";// 终端IP(必填)
                                formData  += "<total_fee>"+paramForSign.total_fee+"</total_fee>";// 总金额(必填)
                                formData  += "<trade_type>"+paramForSign.trade_type+"</trade_type>";// 交易类型(必填)
                                formData  += "<sign>"+payUtil.calcWxPaySign(key, paramForSign)+"</sign>";
                                formData  += "</xml>";

                                payUtil.reqWxApi_payUniOrd(key, formData, function(retErr, retInfo){
                                    if(retErr) {
                                        return callback(retErr, null);
                                    }

                                    if(retInfo && retInfo.prepay_id) {
                                        // 统一下单接口返回正常的prepay_id, 再按签名规范重新生成签名后, 将数据传输给APP。
                                        // 参与签名的字段名为appId, partnerId, prepayId, nonceStr, timeStamp, package。
                                        // 注意: package的值格式为Sign=WXPay

                                        //var paramForSign2 = {
                                        //    appId: appid,
                                        //    partnerId: mch_id,
                                        //    prepayId: retInfo.prepay_id,
                                        //    nonceStr: payUtil.genNonceStr(32),
                                        //    timeStamp: Math.floor(Date.now()/1000)+"",
                                        //    package: "Sign=WXPay"
                                        //};

                                        var paramForSign2 = {};
                                        var ns = payUtil.genNonceStr(32);
                                        var ts = Math.floor(Date.now()/1000)+"";

                                        if(H5PayFlg) {// 内嵌H5支付
                                            paramForSign2 = {// 参数名区分大小写 !!!???
                                                appId: appid,
                                                timeStamp: ts,
                                                nonceStr: ns,
                                                package: "prepay_id="+retInfo.prepay_id,
                                                signType: 'MD5'
                                            };

                                        } else {// APP,网页支付
                                            paramForSign2 = {// 巨坑: 参数名需要小写 !!!???
                                                appid: appid,
                                                partnerid: mch_id,
                                                prepayid: retInfo.prepay_id,
                                                noncestr: ns,
                                                timestamp: ts,
                                                package: "Sign=WXPay"
                                            };
                                        }

                                        var sign2 = payUtil.calcWxPaySign(key, paramForSign2);

                                        return callback(null, {
                                            prepayId:retInfo.prepay_id,
                                            nonceStr:ns,
                                            timeStamp:ts,
                                            sign:sign2
                                        });

                                    } else {
                                        return callback('预支付交易会话标识获取失败', null);
                                    }
                                });
                            }
                        }
                    );

                }else{
                    return callback(error, null);
                }
            }, 0, 1);

        } else {
            return callback('无效订单分类', null);
        }
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 调用微信支付[统一下单]API (网页扫码支付用)
     * @param device
     * @param userId
     * @param tradeObjId: order_id 或 inv_id
     * @param type: 商品订单:10, 发票订单:20, 虚拟商品:40
     * @param callback
     *  {
     *      "prepay_id": "wx20170301114917740287da3c0256350262",
     *      "code_url": "weixin://wxpay/bizpayurl?pr=8RODogK",// 二维码链接
     *   }
     */
    payUtil.getUnifiedOrderWeb = function(device, userId, tradeObjId, type, callback) {

        // Parameter
        var timeStamp = Math.floor(Date.now()/1000)+"";// 时间戳

        // 附加数据: 暂定纪录userId,tradeObjId,type
        var attach = JSON.stringify({
            uid: userId||0, id: tradeObjId||0, type: type||0
        });

        // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数
        // 支付成功后微信服务器通过POST请求通知这个地址
        var notify_url = 'https://paycb.itbour.com:818/payment/chkWxPayNotify';
        if(CONFIG.DEBUG) {
            notify_url = 'http://paycb.itbour.com/payment/chkWxPayNotify';
        }

        var key = ITB_WX_INFO.KEY;

        var paramForSign = {
            appid:              ITB_WX_INFO.APPID,// 应用ID(必填)
            attach:             attach,
            body:               "示界港微信支付订单",// 商品或支付单简要描述 TODO
            device_info:        'WEB',
            mch_id:             ITB_WX_INFO.MCH_ID,// 商户号(必填)
            nonce_str:          payUtil.genNonceStr(32),// 随机字符串,不长于32位(必填)
            notify_url:         notify_url,
            out_trade_no:       '',// 商户订单号(必填)
            spbill_create_ip:   "127.0.0.1",// 终端IP(必填) TODO
            total_fee:          0,// 总金额(必填)
            trade_type:         'NATIVE',// 交易类型(必填): APP/JSAPI/NATIVE(会返回code_url)
        };

        // 获取订单信息
        if(type == 10 || type == 20 || type == 40 || type == 50) {
            var orderEnt = null;

            if(type == 10 || type == 40 || type == 50) {// 商品订单
                orderEnt = new ItbTradeOrderModel({
                    order_id: tradeObjId,
                    del_flg: 0
                });
            } else if(type == 20){// 发票订单
                orderEnt = new ItbInvoiceModel({
                    inv_id: tradeObjId,
                    del_flg: 0
                });
            }
            orderEnt.findFromDB(function(error, data){
                if(data && data.length>0){

                    if(Number(data[0].state || 0) == 50) {
                        return callback('该订单因超时已取消，请重新下单！', null);
                    }

                    if(type == 10 || type == 40 || type == 50) {
                        paramForSign.out_trade_no = data[0].order_no;
                        paramForSign.total_fee = data[0].total_fee || 0;// 商品订单总金额
                    } else if(type == 20) {
                        paramForSign.out_trade_no = data[0].inv_no;
                        paramForSign.total_fee = data[0].mail_fee || 0;// 发票只算邮费
                    }

                    // 先统一更新为[支付失败]
                    payUtil.updOrderState(tradeObjId, type, 12, paramForSign.total_fee, userId,
                        function(updErr, updRet){
                            if (updErr) {
                                console.log("payUtil.js [getUnifiedOrderWeb] Upd State(12) Err: " + updErr);
                                return callback(updErr, null);
                            }

                            // 开始支付
                            if(paramForSign.total_fee == 0) {// 免费不用支付
                                // 添加支付历史纪录
                                var insEnt = new ItbPaymentHisModel({
                                    type: type||0,
                                    trade_obj_id: tradeObjId||0,
                                    trade_obj_no: paramForSign.out_trade_no||0,
                                    state: 11,
                                    pay_platform: 0,// 无
                                    desc: 'SUCCESS',
                                    update_by: userId||0
                                });
                                insEnt.saveToDB(function(insErr, newHisId) {
                                    if (insErr) {
                                        console.log("payUtil.js [getUnifiedOrderWeb] Ins PayHis Err: " + insErr);
                                    }
                                    // 更新为[支付成功]
                                    payUtil.updOrderState(tradeObjId, type, 11, 0, userId,
                                        function(updErr2, updRet2){
                                            return  callback(updErr2, updRet2);
                                        }
                                    );

                                    // TODO 根据订单类型分别处理
                                });

                            } else {// 需要支付
                                // 调用微信下单接口
                                var formData  = "<xml>";
                                formData  += "<appid>"+paramForSign.appid+"</appid>";  // 应用ID(必填)
                                formData  += "<attach>"+paramForSign.attach+"</attach>"; // 附加数据
                                formData  += "<body>"+paramForSign.body+"</body>";// 商品或支付单简要描述
                                formData  += "<device_info>"+paramForSign.device_info+"</device_info>";
                                formData  += "<mch_id>"+paramForSign.mch_id+"</mch_id>";// 商户号(必填)
                                formData  += "<nonce_str>"+paramForSign.nonce_str+"</nonce_str>";// 随机字符串,不长于32位(必填)
                                formData  += "<notify_url>"+paramForSign.notify_url+"</notify_url>";// 通知地址(必填)
                                //formData  += "<openid>"+paramForSign.openid+"</openid>";
                                formData  += "<out_trade_no>"+paramForSign.out_trade_no+"</out_trade_no>";// 商户订单号(必填)
                                formData  += "<spbill_create_ip>"+paramForSign.spbill_create_ip+"</spbill_create_ip>";// 终端IP(必填)
                                formData  += "<total_fee>"+paramForSign.total_fee+"</total_fee>";// 总金额(必填)
                                formData  += "<trade_type>"+paramForSign.trade_type+"</trade_type>";// 交易类型(必填)
                                formData  += "<sign>"+payUtil.calcWxPaySign(key, paramForSign)+"</sign>";
                                formData  += "</xml>";

                                payUtil.reqWxApi_payUniOrd(key, formData, function(retErr, retInfo){
                                    if(retErr) {
                                        return callback(retErr, null);
                                    }

                                    if(retInfo && retInfo.prepay_id && retInfo.code_url) {
                                        return callback(null, {
                                            prepay_id:retInfo.prepay_id||'',// 预支付交易会话标识
                                            code_url:retInfo.code_url||''// 二维码链接
                                        });

                                    } else {
                                        return callback('[微信支付二维码]获取失败', null);
                                    }
                                });
                            }
                        }
                    );

                }else{
                    return callback(error, null);
                }
            }, 0, 1);

        } else {
            return callback('无效订单分类', null);
        }
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 调用微信支付[统一下单]API (APP购买模板用)
     * @param device
     * @param userId
     * @param openId (微信H5支付用)
     * @param typeL: 模版类型
     * @param tmplId: 模版id
     * @param callback
     *  {
     *      "prepayId": 1234567,
     *      "nonceStr": "qwertyuiopsdfghjkl",
     *      "timeStamp": 999990909090,
     *      "sign": "QWKSJDFHGJHDFHHDHH"
     *   }
     */
    payUtil.getUnifiedOrderForTmpl = function(device, userId, openId, typeL, tmplId, callback) {

        var H5PayFlg = false;
        if(device == '5' || device == '201' || device == '301') {// 微信内嵌H5支付
            H5PayFlg = true;
        }

        // Parameter
        var timeStamp = Math.floor(Date.now()/1000)+"";// 时间戳
        var trade_type = "APP";// 交易类型(必填): APP/JSAPI/NATIVE(会返回code_url)
        var openid = openId || '';

        // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数
        // 支付成功后微信服务器通过POST请求通知这个地址
        var notify_url = 'https://paycb.itbour.com:818/payment/chkWxPayNotify';
        if(CONFIG.DEBUG) {
            notify_url = 'http://paycb.itbour.com/payment/chkWxPayNotify';
        }
        var appid = ITB_WX_INFO.APPID;// 应用ID(必填)
        var mch_id = ITB_WX_INFO.MCH_ID;// 商户号(必填)
        var key = ITB_WX_INFO.KEY;

        if(H5PayFlg) {
            trade_type = "JSAPI";
            appid = ITB_WX_INFO_2.APPID;
            mch_id = ITB_WX_INFO_2.MCH_ID;
            key = ITB_WX_INFO_2.KEY;
            notify_url = 'https://paycb.itbour.com:818/payment/chkWxPayNotify2';
            if(CONFIG.DEBUG) {
                notify_url = 'http://paycb.itbour.com/payment/chkWxPayNotify2';
            }
        }

        // 附加数据
        var attach = '{}';
        var body = "示界港微信支付订单";// 商品或支付单简要描述 TODO

        var nonce_str = payUtil.genNonceStr(32);// 随机字符串,不长于32位(必填)

        var ip = "127.0.0.1";// 终端IP(必填) TODO

        // 获取订单信息
        if(typeL == 1 || typeL == 2 || typeL==3 || typeL==6 || typeL==7 || typeL==8) {
            var chkEnt = new ItbTmplPriceModel();
            chkEnt.findPriceInfoByType(typeL,tmplId,0,1,function(error, data){
                if(data && data.length>0){
                    var priceInfo = data[0];

                    if(Number(priceInfo.free||0) == 1 || Number(priceInfo.price||0) == 0) {
                        return callback('该模版限时免费中', null);
                    }

                    var buyNo = payUtil.createOrderNo(device, CONFIG.ORDER_TYPE_DB_TEMPLATE);
                    if(!buyNo) {
                        return callback('订单号生成失败', null);
                    }

                    // 创建默认购买订单
                    var m = moment(new Date());
                    var startTime = m.format('YYYY-MM-DD HH:mm:ss');
                    var endTime = m.add(Number(priceInfo.period||0), 'days').format('YYYY-MM-DD')+' 23:59:59';

                    var newEnt = new ItbBuyTmplModel({
                        buy_no: buyNo,
                        device: Number(device||'0')||0,
                        type: typeL,
                        tmpl_id: tmplId,
                        user_id: userId,
                        state: 12,// 支付失败
                        valid_time_start: startTime,
                        valid_time_end: endTime,
                        pay_platform: 10,// 微信
                        total_fee: priceInfo.price,
                        tmpl_price: priceInfo.price,
                        coupon_fee: 0,
                        update_by: userId
                    });
                    newEnt.saveToDB(function(insErr, newId){
                        if(insErr) {
                            console.log('payUtil.js [getUnifiedOrderForTmpl] ItbBuyTmplModel.saveToDB Err: '+insErr);
                            return callback('订单创建失败', null);
                        }

                        attach = JSON.stringify({
                            uid: userId||0,
                            id: newId||0,
                            type: CONFIG.ORDER_TYPE_DB_TEMPLATE,// 订单类型
                        });

                        // 调用微信下单接口
                        var paramForSign = {
                            appid: appid,
                            attach: attach,
                            body: body,
                            mch_id: mch_id,
                            nonce_str: nonce_str,
                            notify_url: notify_url,
                            openid: openid,
                            out_trade_no: buyNo,// 商户订单号(必填)
                            spbill_create_ip: ip,
                            total_fee: priceInfo.price,// 总金额(必填)
                            trade_type: trade_type,
                        };

                        var formData  = "<xml>";
                        formData  += "<appid>"+paramForSign.appid+"</appid>";  // 应用ID(必填)
                        formData  += "<attach>"+paramForSign.attach+"</attach>"; // 附加数据
                        formData  += "<body>"+paramForSign.body+"</body>";// 商品或支付单简要描述
                        formData  += "<mch_id>"+paramForSign.mch_id+"</mch_id>";// 商户号(必填)
                        formData  += "<nonce_str>"+paramForSign.nonce_str+"</nonce_str>";// 随机字符串,不长于32位(必填)
                        formData  += "<notify_url>"+paramForSign.notify_url+"</notify_url>";// 通知地址(必填)
                        formData  += "<openid>"+paramForSign.openid+"</openid>";
                        formData  += "<out_trade_no>"+paramForSign.out_trade_no+"</out_trade_no>";// 商户订单号(必填)
                        formData  += "<spbill_create_ip>"+paramForSign.spbill_create_ip+"</spbill_create_ip>";// 终端IP(必填)
                        formData  += "<total_fee>"+paramForSign.total_fee+"</total_fee>";// 总金额(必填)
                        formData  += "<trade_type>"+paramForSign.trade_type+"</trade_type>";// 交易类型(必填)
                        formData  += "<sign>"+payUtil.calcWxPaySign(key, paramForSign)+"</sign>";
                        formData  += "</xml>";

                        payUtil.reqWxApi_payUniOrd(key, formData, function(retErr, retInfo){
                            if(retErr) {
                                return callback(retErr, null);
                            }

                            if(retInfo && retInfo.prepay_id) {
                                // 统一下单接口返回正常的prepay_id, 再按签名规范重新生成签名后, 将数据传输给APP。
                                // 参与签名的字段名为appId, partnerId, prepayId, nonceStr, timeStamp, package。
                                // 注意: package的值格式为Sign=WXPay

                                var paramForSign2 = {};
                                var ns = payUtil.genNonceStr(32);
                                var ts = Math.floor(Date.now()/1000)+"";

                                if(H5PayFlg) {// 内嵌H5支付
                                    paramForSign2 = {// 参数名区分大小写 !!!???
                                        appId: appid,
                                        timeStamp: ts,
                                        nonceStr: ns,
                                        package: "prepay_id="+retInfo.prepay_id,
                                        signType: 'MD5'
                                    };

                                } else {// APP,网页支付
                                    paramForSign2 = {// 巨坑: 参数名需要小写 !!!???
                                        appid: appid,
                                        partnerid: mch_id,
                                        prepayid: retInfo.prepay_id,
                                        noncestr: ns,
                                        timestamp: ts,
                                        package: "Sign=WXPay"
                                    };
                                }

                                var sign2 = payUtil.calcWxPaySign(key, paramForSign2);

                                return callback(null, {
                                    prepayId:retInfo.prepay_id,
                                    nonceStr:ns,
                                    timeStamp:ts,
                                    sign:sign2
                                });

                            } else {
                                return callback('预支付交易会话标识获取失败', null);
                            }
                        });
                    });

                }else{
                    return callback('未获取到价格信息', null);
                }
            });

        } else {
            return callback('无效模版类型', null);
        }
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 调用微信支付[统一下单]API (网页购买模板用)
     * @param device
     * @param userId
     * @param typeL: 模版类型
     * @param tmplId: 模版id
     * @param callback
     *  {
     *      "prepay_id": "wx20170301114917740287da3c0256350262",
     *      "code_url": "weixin://wxpay/bizpayurl?pr=8RODogK",// 二维码链接
     *   }
     */
    payUtil.getUnifiedOrderForTmplWeb = function(device, userId, typeL, tmplId, callback) {

        // Parameter
        var timeStamp = Math.floor(Date.now()/1000)+"";// 时间戳

        // 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数
        // 支付成功后微信服务器通过POST请求通知这个地址
        var notify_url = 'https://paycb.itbour.com:818/payment/chkWxPayNotify';
        if(CONFIG.DEBUG) {
            notify_url = 'http://paycb.itbour.com/payment/chkWxPayNotify';
        }

        // 获取订单信息
        if(typeL == 1 || typeL == 2 || typeL==3 || typeL==6 || typeL==7 || typeL==8) {
            var chkEnt = new ItbTmplPriceModel();
            chkEnt.findPriceInfoByType(typeL,tmplId,0,1,function(error, data){
                if(data && data.length>0){
                    var priceInfo = data[0];

                    if(Number(priceInfo.free||0) == 1 || Number(priceInfo.price||0) == 0) {
                        return callback('该模版限时免费中', null);
                    }

                    var buyNo = payUtil.createOrderNo(device, CONFIG.ORDER_TYPE_DB_TEMPLATE);
                    if(!buyNo) {
                        return callback('订单号生成失败', null);
                    }

                    // 创建默认购买订单
                    var m = moment(new Date());
                    var startTime = m.format('YYYY-MM-DD HH:mm:ss');
                    var endTime = m.add(Number(priceInfo.period||0), 'days').format('YYYY-MM-DD')+' 23:59:59';

                    var newEnt = new ItbBuyTmplModel({
                        buy_no: buyNo,
                        device: Number(device||'0')||0,
                        type: typeL,
                        tmpl_id: tmplId,
                        user_id: userId,
                        state: 12,// 支付失败
                        valid_time_start: startTime,
                        valid_time_end: endTime,
                        pay_platform: 10,// 微信
                        total_fee: priceInfo.price,
                        tmpl_price: priceInfo.price,
                        coupon_fee: 0,
                        update_by: userId
                    });
                    newEnt.saveToDB(function(insErr, newId){
                        if(insErr) {
                            console.log('payUtil.js [getUnifiedOrderForTmplWeb] ItbBuyTmplModel.saveToDB Err: '+insErr);
                            return callback('订单创建失败', null);
                        }

                        // 附加数据
                        var attach = JSON.stringify({
                            uid: userId||0,
                            id: newId||0,
                            type: CONFIG.ORDER_TYPE_DB_TEMPLATE,// 订单类型
                        });

                        var key = ITB_WX_INFO.KEY;

                        // 调用微信下单接口
                        var paramForSign = {
                            appid:              ITB_WX_INFO.APPID,// 应用ID(必填)
                            attach:             attach,
                            body:               "示界港微信支付订单",// 商品或支付单简要描述 TODO
                            device_info:        "WEB",
                            mch_id:             ITB_WX_INFO.MCH_ID,// 商户号(必填)
                            nonce_str:          payUtil.genNonceStr(32),// 随机字符串,不长于32位(必填)
                            notify_url:         notify_url,
                            out_trade_no:       buyNo,// 商户订单号(必填)
                            spbill_create_ip:   "127.0.0.1",// 终端IP(必填) TODO
                            total_fee:          priceInfo.price,// 总金额(必填)
                            trade_type:         "NATIVE",// 交易类型(必填): APP/JSAPI/NATIVE(会返回code_url)
                        };

                        var formData  = "<xml>";
                        formData  += "<appid>"+paramForSign.appid+"</appid>";  // 应用ID(必填)
                        formData  += "<attach>"+paramForSign.attach+"</attach>"; // 附加数据
                        formData  += "<body>"+paramForSign.body+"</body>";// 商品或支付单简要描述
                        formData  += "<device_info>"+paramForSign.device_info+"</device_info>";
                        formData  += "<mch_id>"+paramForSign.mch_id+"</mch_id>";// 商户号(必填)
                        formData  += "<nonce_str>"+paramForSign.nonce_str+"</nonce_str>";// 随机字符串,不长于32位(必填)
                        formData  += "<notify_url>"+paramForSign.notify_url+"</notify_url>";// 通知地址(必填)
                        //formData  += "<openid>"+paramForSign.openid+"</openid>";
                        formData  += "<out_trade_no>"+paramForSign.out_trade_no+"</out_trade_no>";// 商户订单号(必填)
                        formData  += "<spbill_create_ip>"+paramForSign.spbill_create_ip+"</spbill_create_ip>";// 终端IP(必填)
                        formData  += "<total_fee>"+paramForSign.total_fee+"</total_fee>";// 总金额(必填)
                        formData  += "<trade_type>"+paramForSign.trade_type+"</trade_type>";// 交易类型(必填)
                        formData  += "<sign>"+payUtil.calcWxPaySign(key, paramForSign)+"</sign>";
                        formData  += "</xml>";

                        payUtil.reqWxApi_payUniOrd(key, formData, function(retErr, retInfo){
                            if(retErr) {
                                return callback(retErr, null);
                            }

                            if(retInfo && retInfo.prepay_id && retInfo.code_url) {
                                return callback(null, {
                                    prepay_id:retInfo.prepay_id||'',// 预支付交易会话标识
                                    code_url:retInfo.code_url||''// 二维码链接
                                });

                            } else {
                                return callback('[微信支付二维码]获取失败', null);
                            }
                        });
                    });

                }else{
                    return callback('未获取到价格信息', null);
                }
            });

        } else {
            return callback('无效模版类型', null);
        }
    };

    //--------------------------------------------------------------------------------------------
    /**
     * (微信／支付宝)支付回调成功后续处理
     * @param param 参数对象
     *      {
     *          "userId": 123,      // 用户id
     *          "tradeType": 10,    // 订单类型: 10商品订单, 20发票订单, 30模版订单, 40虚拟商品(vip等), 50秒杀订单
     *          "tradeObjId": 1221, // 订单id
     *          "tradeState": 11,   // 支付状态: 11成功, 12失败
     *          "totalFee": 1000,   // 订单支付总金额(单位:分)
 *          }
     * @param callback
     */
    payUtil.payNotifyProcCore = function(param, callback) {
        if(!param
            || !param.userId
            || !param.tradeType
            || !param.tradeObjId
            || Number(param.totalFee||'0')<0
        ) {
            return callback('参数错误', null);
        }

        payUtil.updOrderState(param.tradeObjId, param.tradeType, param.tradeState, param.totalFee, param.userId,
            function(updErr, updRet){

                // added 2017-06-14
                if(Number(param.tradeType||'0')==10 && param.tradeState==11) {
                    // 尝试拆分支付成功的商品订单
                    payUtil.splitTradeOrder_v5_5(param.tradeObjId, param.userId, function(procErr, procRet){
                        if(procErr) {
                            console.log("payUtil.js [payNotifyProcCore] splitTradeOrder_v5_5 Err: "+procErr);
                        }
                        return  callback(updErr, updRet);
                    });

                } else if(Number(param.tradeType||'0')==40){
                    // 虚拟商品特殊处理: 支付成功时直接[完成], 否则[取消]
                    var updState = 50;
                    if(param.tradeState==11) {
                        updState = 40;
                    }
                    payUtil.updOrderState(param.tradeObjId, param.tradeType, updState,
                        param.totalFee, param.userId, function(updErr2, updRet2){

                            // 更新vip会员信息
                            if(param.tradeState==11) {
                                payUtil.updVipExpiryInfo(param.userId, param.tradeObjId, function(updErr3, updRet3){
                                    return callback(updErr3, updRet3);
                                });
                            } else {
                                return callback(updErr2, updRet2);
                            }
                        }
                    );

                } else if(Number(param.tradeType||'0')==50) {
                    // 秒杀订单
                    if(param.tradeState==11) {
                        // 支付成功
                        // 获取秒杀商品
                        (new ItbTradeOrderModel).getSeckillOrderItemInfo(param.tradeObjId, function(getErr, getRet){
                            if(getErr) {
                                console.log("payUtil.js [payNotifyProcCore] getSeckillOrderItemInfo Err: "+getErr);
                                return callback(getErr, null);
                            }
                            if(getRet && getRet.r_id) {

                                // 更新锁定商品状态
                                luaUtil.updLockActItemSuccess(getRet.r_id, param.userId, function(procErr, procRet){
                                    if(procErr) {
                                        console.log("payUtil.js [payNotifyProcCore] updLockActItemSuccess Err: "+procErr);
                                        return callback(procErr, null);// 更新失败直接返回
                                    }

                                    console.log('payUtil.js [payNotifyProcCore] updLockActItemSuccess Ret: '+procRet);
                                    if(procRet!=0) {// 0表示成功，1表示不存在场次或商品，2表示用户未加锁
                                        // 更新锁失败
                                        return callback('Upd rds lock success NG',null);
                                    }

                                    // 更新秒杀订单状态
                                    payUtil.updOrderState(param.tradeObjId, param.tradeType, 40/*完成*/,
                                        param.totalFee, param.userId, function(updErr2, updRet2){

                                            // 创建真正的商品订单
                                            if(param.tradeState==11) {
                                                console.log("payUtil.js [payNotifyProcCore] Create Seckill RealItemOdr START");
                                                payUtil.createSeckillRealItemOrder_v6_1(param.userId, param.tradeObjId, function(procErr, procRet){
                                                    console.log("payUtil.js [payNotifyProcCore] Create Seckill RealItemOdr END");
                                                    return callback(procErr, procRet);
                                                });
                                            } else {
                                                return callback(updErr2, updRet2);
                                            }
                                        }
                                    );
                                });
                            } else {
                                return callback('无效秒杀订单', null);
                            }
                        });
                    } else {
                        // 支付失败
                        payUtil.updOrderState(param.tradeObjId, param.tradeType, 50/*取消*/,
                            param.totalFee, param.userId, function(updErr2, updRet2){
                                return callback(updErr2, updRet2);
                            }
                        );
                    }

                } else {
                    return  callback(updErr, updRet);
                }
            }
        );
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 检查微信支付回调信息
     * @param key
     * @param dataObj
     * @param callback
     */
    payUtil.chkWxPayNotifyProc = function(key, dataObj, callback){
        // 推荐的做法是，当收到通知进行处理时，首先检查对应业务数据的状态，判断该通知是否已经处理过，如果没有处理过再进行处理，如果处理过直接返回结果成功。
        // 在对业务数据进行状态检查和处理之前，要采用数据锁进行并发控制，以避免函数重入造成的数据混乱。
        // 特别提醒：商户系统对于支付结果通知的内容一定要做签名验证，防止数据泄漏导致出现“假通知”，造成资金损失。

        if(!dataObj) {
            return('Empty Notify Data', null);
        }

        if((dataObj.return_code||'')=='SUCCESS'){// 此字段是通信标识，非交易标识，交易是否成功需要查看result_code来判断
            // 获取微信回调签名
            var retSign = dataObj.sign;// 微信返回的都是大写!!??

            // 验证微信回调签名
            delete dataObj.sign;
            var calSign = payUtil.calcWxPaySign(key, dataObj);

            console.log('retSign:['+retSign+'] calSign:['+calSign+']');
            if(!retSign || !calSign || retSign.toUpperCase() != calSign.toUpperCase()) {
                return callback('非法通知数据', null);
            }

            var tradeState = '0';
            if((dataObj.result_code||'')=='SUCCESS'){
                tradeState = 11;// 支付成功
            } else {
                tradeState = 12;// 支付失败
            }

            // 检查纪录是否已存在
            var chkEnt = new ItbPaymentHisModel({
                trade_obj_no: dataObj.out_trade_no,
                state: tradeState,
                del_flg:0
            });
            chkEnt.findFromDB(function(chkErr, chkRet){
                if(chkErr) {
                    console.log("payUtil.js [chkWxPayNotifyProc] find Err: "+chkErr);
                }

                if(chkRet && chkRet.length>0) {
                    // 已存在
                    return callback(null, null);// TODO

                } else {
                    // 附加信息: 包含用户id,订单类型,订单id
                    var attach = JSON.parse(dataObj.attach||'{}');

                    // 添加支付历史纪录
                    var insEnt = new ItbPaymentHisModel({
                        type: attach.type||0,// 订单类型
                        trade_obj_id: attach.id||0,
                        trade_obj_no: dataObj.out_trade_no||0,
                        state: tradeState,
                        pay_platform: 10,// 微信
                        desc: 'SUCCESS',
                        pay_info1: dataObj.return_code||'',
                        pay_info2: dataObj.return_msg||'',
                        pay_info3: dataObj.appid||'',
                        pay_info4: dataObj.mch_id||'',
                        pay_info5: dataObj.device_info||'',
                        pay_info6: dataObj.nonce_str||'',
                        pay_info7: dataObj.sign||'',
                        pay_info8: dataObj.result_code||'',
                        pay_info9: dataObj.err_code||'',
                        pay_info10: dataObj.err_code_des||'',
                        pay_info11: dataObj.openid||'',
                        pay_info12: dataObj.is_subscribe||'',
                        pay_info13: dataObj.trade_type||'',
                        pay_info14: dataObj.bank_type||'',
                        pay_info15: dataObj.total_fee||0,
                        pay_info16: dataObj.fee_type||'',
                        pay_info17: dataObj.cash_fee||0,
                        pay_info18: dataObj.cash_fee_type||'',
                        pay_info19: dataObj.coupon_fee||0,
                        pay_info20: dataObj.coupon_count||0,
                        pay_info21: dataObj.transaction_id||'',
                        pay_info22: dataObj.out_trade_no||'',
                        pay_info23: dataObj.attach||'',
                        pay_info24: dataObj.time_end||'',
                        //pay_info25: '',
                        update_by: attach.uid||0
                    });
                    insEnt.saveToDB(function(insErr, newHisId){
                        if(insErr) {
                            console.log("payUtil.js [chkWxPayNotifyProc] Ins PayHis Err: "+insErr);
                        }


                        // 统一后续处理
                        var param = {
                            userId: attach.uid,
                            tradeType: attach.type,
                            tradeObjId: attach.id,
                            tradeState: tradeState,
                            totalFee: dataObj.total_fee,
                        };
                        payUtil.payNotifyProcCore(param, function(procErr, procRet){
                            if (procErr) {
                                console.log("payUtil.js [chkWxPayNotifyProc] payNotifyProcCore Err: "+procErr);
                            }
                            return callback(procErr, procRet);
                        });

                        //payUtil.updOrderState(attach.id, attach.type, tradeState, dataObj.total_fee, attach.uid,
                        //    function(updErr, updRet){
                        //
                        //        // added 2017-06-14
                        //        if(Number(attach.type||'0')==10 && tradeState==11) {
                        //            // 尝试拆分支付成功的商品订单
                        //            payUtil.splitTradeOrder_v5_5(attach.id, attach.uid, function(procErr, procRet){
                        //                if(procErr) {
                        //                    console.log("payUtil.js [chkWxPayNotifyProc] splitTradeOrder_v5_5 Err: "+procErr);
                        //                }
                        //                return  callback(updErr, updRet);
                        //            });
                        //
                        //        } else if(Number(attach.type||'0')==40){
                        //            // 虚拟商品特殊处理: 支付成功时直接[完成], 否则[取消]
                        //            var updState = 50;
                        //            if(tradeState==11) {
                        //                updState = 40;
                        //            }
                        //            payUtil.updOrderState(attach.id, attach.type, updState,
                        //                dataObj.total_fee, attach.uid, function(updErr2, updRet2){
                        //
                        //                    // 更新vip会员信息
                        //                    if(tradeState==11) {
                        //                        payUtil.updVipExpiryInfo(attach.uid, attach.id, function(updErr3, updRet3){
                        //                            return callback(updErr3, updRet3);
                        //                        });
                        //                    } else {
                        //                        return callback(updErr2, updRet2);
                        //                    }
                        //                }
                        //            );
                        //
                        //        } else if(Number(attach.type||'0')==50) {
                        //            // 秒杀订单
                        //            if(tradeState==11) {
                        //                // 支付成功
                        //                // 获取秒杀商品
                        //                (new ItbTradeOrderModel).getSeckillOrderItemInfo(attach.id, function(getErr, getRet){
                        //                    if(getErr) {
                        //                        console.log("payUtil.js [chkWxPayNotifyProc] getSeckillOrderItemInfo Err: "+getErr);
                        //                        return callback(getErr, null);
                        //                    }
                        //                    if(getRet && getRet.r_id) {
                        //
                        //                        // 更新锁定商品状态
                        //                        luaUtil.updLockActItemSuccess(getRet.r_id, attach.uid, function(procErr, procRet){
                        //                            if(procErr) {
                        //                                console.log("payUtil.js [chkWxPayNotifyProc] updLockActItemSuccess Err: "+procErr);
                        //                                return callback(procErr, null);// 更新失败直接返回
                        //                            }
                        //
                        //                            console.log('payUtil.js [createSeckillRealItemOrder_v6_1] updLockActItemSuccess Ret: '+procRet);
                        //                            if(procRet!=0) {// 0表示成功，1表示不存在场次或商品，2表示用户未加锁
                        //                                // 更新锁失败
                        //                                return callback('Upd rds lock success NG',null);
                        //                            }
                        //
                        //                            // 更新秒杀订单状态
                        //                            payUtil.updOrderState(attach.id, attach.type, 40/*完成*/,
                        //                                dataObj.total_fee, attach.uid, function(updErr2, updRet2){
                        //
                        //                                    // 创建真正的商品订单
                        //                                    if(tradeState==11) {
                        //                                        console.log("payUtil.js [chkWxPayNotifyProc] Create Seckill RealItemOdr START");
                        //                                        payUtil.createSeckillRealItemOrder_v6_1(attach.uid, attach.id, function(procErr, procRet){
                        //                                            console.log("payUtil.js [chkWxPayNotifyProc] Create Seckill RealItemOdr END");
                        //                                            return callback(procErr, procRet);
                        //                                        });
                        //                                    } else {
                        //                                        return callback(updErr2, updRet2);
                        //                                    }
                        //                                }
                        //                            );
                        //                        });
                        //                    } else {
                        //                        return callback('无效订单', null);
                        //                    }
                        //                });
                        //            } else {
                        //                // 支付失败
                        //                payUtil.updOrderState(attach.id, attach.type, 50/*取消*/,
                        //                    dataObj.total_fee, attach.uid, function(updErr2, updRet2){
                        //                        return callback(updErr2, updRet2);
                        //                    }
                        //                );
                        //            }
                        //
                        //        } else {
                        //            return  callback(updErr, updRet);
                        //        }
                        //    }
                        //);
                    });
                }
            });

        } else {
            var attach = JSON.parse(dataObj.attach||'{}');
            // 失败
            var errEnt = new ItbPaymentHisModel({
                type: attach.type||0,
                trade_obj_id: attach.id||0,
                state: 12,// 支付失败
                pay_platform: 10,// 微信
                pay_info1: dataObj.return_code||'',
                pay_info2: dataObj.return_msg||'',
                desc: 'Wechat notify [return_code] is not SUCCESS'
            });
            errEnt.saveToDB(function(insErr, newId){
                if(insErr) {
                    console.log("payUtil.js [chkWxPayNotifyProc] InsErr Err: "+insErr);
                }
                return callback((dataObj.return_msg||'回调状态失败'), null);
            });
        }
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 检查微信支付回调信息
     * @param dataObj
     * @param callback
     */
    payUtil.chkWxPayNotify = function(dataObj, callback){
        payUtil.chkWxPayNotifyProc(ITB_WX_INFO.KEY, dataObj, callback);// APP
    };
    // 微信H5支付用回调
    payUtil.chkWxPayNotify2 = function(dataObj, callback){
        payUtil.chkWxPayNotifyProc(ITB_WX_INFO_2.KEY, dataObj, callback);// H5
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 更新订单状态
     * @param tradeObjId: 订单id
     * @param tradeType:  10商品订单 20发票订单
     * @param tradeState: 订单状态
     * @param userId:     更新者
     * @param callback     返回
     *          error   错误，null表示整你却
     *          data    预留null
     */
    payUtil.updOrderStateOnly = function(tradeObjId, tradeType, tradeState,userId, callback){
        // 更新订单状态
        if((Number(tradeType||0)==10 || Number(tradeType||0)==20) && tradeObjId) {
            var updEnt = null;
            if(Number(tradeType||0)== 10) {
                // 商品订单
                updEnt = new ItbTradeOrderModel({
                    order_id: tradeObjId||0,
                    state: tradeState||0,
                    update_by: userId||''
                });
            } else if(Number(tradeType||0)== 20) {
                // 发票订单
                updEnt = new ItbInvoiceModel({
                    inv_id: tradeObjId||0,
                    state: tradeState||0,
                    update_by: userId||'0'
                });
            } else{
                return callback(null,null);
            }
            updEnt.updateToDB(function(updErr){
                if(updErr){
                    console.log("payUtil.js [updOrderStateOnly] Upd State Err: "+updErr);
                    var desc = '[ItbTradeOrderModel/ItbInvoiceModel] update [state] error';
                    return callback(desc,null);
                }

                return callback(null, null);
            });

        } else {
            return callback(null, null);// TODO
        }
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 根据订单状态更新优惠券状态
     * @param tradeObjId: 订单id
     * @param tradeType:  10商品订单 20发票订单 30模版订单 40虚拟商品
     * @param tradeState: 订单状态
     * @param userId:     更新者
     * @param callback
     */
    payUtil.updConponState = function(tradeObjId, tradeType, tradeState, userId, callback) {
        if(Number(tradeType||'0')==10 || Number(tradeType||'0')==40 || Number(tradeType||'0')==50) {// 可用优惠券的订单类型

            if(tradeState==11) {
                // 支付成功
                (new ItbCouponModel).updStateByPaidOrder(tradeObjId, function(err, ret){
                    return callback(err, ret);
                });
            } else if(tradeState==50) {
                // 订单取消,解绑优惠券
                (new ItbCouponModel).unbindCanceledOrderOnly(tradeObjId, function(err, ret){
                    return callback(err, ret);
                });
            } else {
                return callback(null, null);
            }

        } else {
            return callback(null, null);
        }
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 更新订单状态
     * @param tradeObjId: 订单id
     * @param tradeType:  10商品订单 20发票订单 30模版订单 40虚拟商品 50秒杀订单
     * @param tradeState: 订单状态
     * @param totalFee:   订单金额
     * @param userId:     更新者
     * @param callback
     */
    payUtil.updOrderState = function(tradeObjId, tradeType, tradeState, totalFee, userId, callback){

        tradeType = Number(tradeType||'0')||0;

        // 更新订单状态
        if( (tradeType==10 || tradeType==20 || tradeType==30 || tradeType==40 || tradeType==50)
            && tradeObjId ) {

            var updEnt = null;
            var hisDesc = '';
            if(tradeType== 10 || tradeType== 40 || tradeType==50) {
                // 商品订单
                updEnt = new ItbTradeOrderModel({
                    order_id: tradeObjId||0,
                    state: tradeState||0,
                    update_by: userId||''
                });
                if(tradeState==40) {
                    // 订单完成:需同步设置完成时间
                    updEnt.arrUpdSysDtFieldNm=['finish_time'];
                }
                hisDesc = '[ItbTradeOrderModel] Upd to [state:'+tradeState+']';

            } else if(tradeType== 20) {
                // 发票订单
                updEnt = new ItbInvoiceModel({
                    inv_id: tradeObjId||0,
                    state: tradeState||0,
                    update_by: userId||'0'
                });
                hisDesc = '[ItbInvoiceModel] Upd to [state:'+tradeState+']';

            } else if(tradeType== 30) {
                // 模版订单
                updEnt = new ItbBuyTmplModel({
                    buy_id: tradeObjId||0,
                    state: tradeState||0,
                    update_by: userId||'0'
                });
                hisDesc = '[ItbBuyTmplModel] Upd to [state:'+tradeState+']';
            }
            updEnt.updateToDB_SysDt(function(updErr){
                if(updErr){
                    console.log("payUtil.js [updOrderState] Upd State Err: "+updErr);
                    hisDesc += ' NG';
                } else {
                    hisDesc += ' OK';
                }

                // 添加状态变更纪录
                var hisEnt = new ItbTradeStateHisModel({
                    type: tradeType||0,
                    trade_obj_id: tradeObjId||0,
                    state: tradeState,
                    total_fee: totalFee||0,
                    desc: hisDesc,
                    user_id: userId||0,
                    update_by: userId||'0'
                });
                hisEnt.saveToDB(function(insErr, newHisId){
                    if(insErr){
                        console.log("payUtil.js [updOrderState] Ins StateHis Err: "+insErr);
                        return callback(insErr,null);
                    }

                    // 更新绑定的优惠券状态
                    payUtil.updConponState(tradeObjId, tradeType, tradeState, userId, function(updErr, updRet){

                        if(tradeType==10 || tradeType==20) {
                            // 在订单支付完成时:取得订单的快递地址，到“用户地址管理”表中查找是否有相同纪录，如果没有则拷贝地址到“用户地址管理”表
                            if(tradeState!=CONFIG.TRADE_ORDER_STATE_PAY_SUCCESS){
                                return callback(null,null);
                            }

                            payUtil.tryCopyOrderAddressToUser(tradeObjId, tradeType, function (error, newUserAddressId) {
                                // 不用处理错误消息
                                return callback(null, null);
                            });

                        } else {
                            return callback(null, null);
                        }

                    });

                });
            });

        } else {
            return callback(null, null);// TODO
        }
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 取得订单的快递地址，到“用户地址管理”表中查找是否有相同纪录，如果没有则拷贝地址到“用户地址管理”表
     * @param tradeObjId: 订单id
     * @param tradeType:  10商品订单 20发票订单
     * @param callback  回调，参数如下：
     *                      error：错误
     *                      newUserAddressId： 新的用户地址
     */
    payUtil.tryCopyOrderAddressToUser = function(tradeObjId, tradeType, callback){
        var orderEnt = null;

        // 取得订单地址
        if(tradeType == 10) {// 商品订单
            orderEnt = new ItbTradeOrderModel({
                order_id: tradeObjId,
                del_flg: 0
            });
        } else if(tradeType == 20){// 发票订单
            orderEnt = new ItbInvoiceModel({
                inv_id: tradeObjId,
                del_flg: 0
            });
        }
        orderEnt.findAddressFromDB(function(error, address){
            if(address){
                // 到“用户地址管理”表中查找是否有相同纪录，如果没有则拷贝地址到“用户地址管理”表
                (new ItbAddressModel).insertUserAddressIfNotExist(address, function(error, newUserAddressId){
                     return callback(error,newUserAddressId);
                });
            }else{
                return callback(error ,null);
            }

        });
    };

    //--------------------------------------------------------------------------------------------
    payUtil.checkWxOrder = function (device, userId, tradeObjNo, type, callback) {
        var appid = ITB_WX_INFO.APPID;
        var mchid = ITB_WX_INFO.MCH_ID;
        var key = ITB_WX_INFO.KEY;

        if(device == '5' || device == '201' || device == '301') {
            appid = ITB_WX_INFO_2.APPID;
            mchid = ITB_WX_INFO_2.MCH_ID;
            key = ITB_WX_INFO_2.KEY;
        }

        // Parameter
        var paramForSign = {
            appid: appid,//
            mch_id: mchid,// 微信支付分配的商户号
            nonce_str: payUtil.genNonceStr(32),// 随机字符串，不长于32位
            // transaction_id／out_trade_no二选一
            // transaction_id: 微信的订单号，优先使用
            out_trade_no: tradeObjNo,// 商户系统内部的订单号，当没提供transaction_id时需要传这个
        };

        var formData  = "<xml>";
        formData  += "<appid>"+paramForSign.appid+"</appid>";
        formData  += "<mch_id>"+paramForSign.mch_id+"</mch_id>";
        formData  += "<nonce_str>"+paramForSign.nonce_str+"</nonce_str>";
        formData  += "<out_trade_no>"+paramForSign.out_trade_no+"</out_trade_no>";
        formData  += "<sign>"+payUtil.calcWxPaySign(key, paramForSign)+"</sign>";
        formData  += "</xml>";

        var url = "https://api.mch.weixin.qq.com/pay/orderquery";
        request({url:url,method:'POST',body: formData},function(err,response,retBody){
            if(!err && response.statusCode == 200){
                console.log(retBody);

                var parser = new xml2js.Parser({ trim:true, explicitArray:false, explicitRoot:false });
                parser.parseString((retBody||'').toString("utf-8"), function(parseErr, parseRet){
                    if(parseErr) {
                        console.log('payUtil.js [checkOrder] parser xml Err: '+parseErr);
                        return callback(parseErr, null);
                    }

                    if((parseRet.return_code||'')=='SUCCESS') {

                        if((parseRet.result_code||'')=='SUCCESS') {
                            return callback(null, {trade_state:parseRet.trade_state||''});
                        } else {
                            return callback(parseRet.err_code||'[WX查询订单]获取失败', null);
                        }

                    } else {
                        return callback(parseRet.return_msg||'WXAPI[orderquery]调用失败', null);
                    }
                });
            } else {
                return callback(err, null);
            }
        });
    };

    /**
     * 调用微信支付[查询订单]API
     * @param device
     * @param userId
     * @param tradeObjNo: order_no 或 inv_no
     * @param type: 商品订单:10, 发票订单:20, 虚拟商品:40
     * @param callback
     *   {
     *      "trade_state": SUCCESS
     *   }
     */
    payUtil.checkOrder = function(device, userId, tradeObjNo, type, callback) {
        var totalTasks = [];
        // 1. 查询当前订单
        totalTasks.push(function (callback) {
            var entity = null;
            if(type === 20) {
                entity = new ItbInvoiceModel({
                    inv_no : tradeObjNo,
                    del_flg : 0
                });
            } else {
                entity = new ItbTradeOrderModel({
                    order_no : tradeObjNo,
                    del_flg : 0
                });
            }
            entity.findFromDB(function (error, results) {
                if(error || !results || results.length <=0) {
                    return callback(error || '该订单不存在', null);
                }
                var data = {};
                data.orders = results;
                data.orderEntity = results[0];
                data.payPlatform = data.orderEntity.pay_platform;
                if(data.payPlatform !== 10 && data.payPlatform !== 20) {
                    return callback('暂不支持查询该类型订单', null);
                }
                return callback(error, data);
            });
        });
        // 2.按需查询微信
        totalTasks.push(function (data, callback) {
            if(data.payPlatform !== 10) {
                return callback(null, data);
            }
            payUtil.checkWxOrder(device, userId, tradeObjNo, type, function (error, result) {
                data.wxRet = result;
                data.ret = result;
                return callback(error, data);
            })
        });
        // 3.按需查询支付宝
        totalTasks.push(function (data, callback) {
            if(data.payPlatform !== 20) {
                return callback(null, data);
            }
            var opt = {
                outTradeId : tradeObjNo
            };
            yjscAlipayClient.query(opt)
                .then(function (result) {
                    data.aliRet = null;
                    try {
                        data.aliRet = JSON.parse(result.body);
                    } catch (err) {
                        return callback(err, null);
                    }
                    // 支付成功, 为兼容老接口返回值设置
                    data.ret = {};
                    if(data.aliRet.alipay_trade_query_response &&
                        data.aliRet.alipay_trade_query_response.trade_status &&
                        (data.aliRet.alipay_trade_query_response.trade_status === 'TRADE_SUCCESS' ||
                        data.aliRet.alipay_trade_query_response.trade_status === 'TRADE_FINISHED')) {
                        data.ret.trade_state = 'SUCCESS';
                    } else {
                        data.ret.trade_state = data.aliRet.trade_state;
                    }
                    return callback(null, data);
                })
                .catch(function (error) {
                    return callback(error, null);
                })
        });
        async.waterfall(totalTasks, function (error, data) {
            if(error) {
                return callback(error, null);
            }
            return callback(error, data.ret);
        });
    };

    //------------------------------------- 获取订单状态 -------------------------------------------
    /**
     * 获取订单状态
     * orderId 商品订单 id
     * userId  用户 id
     * callback  回调
     *      err: 错误原因, 'no such order', 标记订单不存在
     *      state : 订单状态: '订单状态:10待支付、11已支付、12支付失败、20制作中、30配送中、40完成、50取消',
     * */
    payUtil.getTradeOrderState_v5_2 = function(orderId, userId, callback){
        var order = new ItbTradeOrderModel({
            order_id : orderId,
            del_flg : 0,
            user_id : userId
        });

        order.findFromDB(function(error, items){
            if(error) {
                console.log('/util/payUtil.js [getOrderState_v5_2] err:', err);
                return callback(error, null);
            }
            if(items.length != 1){
                return callback('no such order', null);
            }

            return callback(null, items[0].state);

        });
    };
    // todo 新增接口, 待审核 end


    //--------------------------------------------------------------------------------------------
    /**
     * 根据不同合作方拆分已付款成功的订单
     * @param orderId 原总订单id
     * @param userId
     */
    payUtil.splitTradeOrder_v5_5 = function(orderId, userId, callback){
        // 1.获取原始订单信息
        var chkEnt = new ItbTradeOrderModel({
            order_id: orderId,
            type: 0,// 未拆分的订单
            state: 11, // 已支付
            user_id: userId,
            del_flg: 0
        });
        chkEnt.findFromDB(function(chkErr, chkRet){
            if(chkErr) {
                console.log('payUtil.js [splitTradeOrder_v5_5] Find OrgOrder Err: ', chkErr);
                return callback(chkErr, null);
            }

            if(chkRet && chkRet.length>0) {
                // 原始总订单
                var orgOrderInfo = chkRet[0];

                // 2.获取原始子订单信息
                var ent = new ItbTradeOrderDetailModel({
                    GroupByPartner: 1// 按照组合商品分组的基础上,按合作方分组
                });
                ent.getPrintProductInfo_v5_5(orderId, function(getErr, getRet){
                    if(getErr) {
                        console.log('payUtil.js [splitTradeOrder_v5_5] getPrintProductInfo_v5_5 Err: ', getErr);
                        return callback(getErr, null);
                    }

                    if(getRet && getRet.length>0) {
                        if(getRet.length==1) {
                            // 无需拆分
                            console.log('payUtil.js [splitTradeOrder_v5_5] No Need ');
                            return callback(null, null);
                        } else {
                            console.log('payUtil.js [splitTradeOrder_v5_5] Do Split ');
                        }

                        // 3.更新原始订单type
                        var updEnt = new ItbTradeOrderModel({
                            order_id: orderId,
                            type: 10,// 被拆分的原始订单
                            hide: 1,// 订单列表中不显示 v6.0
                        });
                        updEnt.updateToDB(function(updErr){
                            if(updErr){
                                console.log('payUtil.js [splitTradeOrder_v5_5] Upd OrgOrder Type(10) Err: ', updErr);
                                return callback(updErr, null);
                            }

                            // 4.分摊优惠金额
                            var totalFeeWithoutMail = 0;
                            for(var i=0; i<getRet.length; i++){
                                totalFeeWithoutMail += (getRet[i].totalProductFee+getRet[i].totalDesignFee);
                                getRet[i].couponFee = 0;// 初始化优惠金额
                            }
                            if(Number(orgOrderInfo.coupon_fee||'0')>0) {
                                // 存在优惠
                                for(var i=0; i<getRet.length; i++){
                                    // 按比例分摊优惠金额
                                    var r = (getRet[i].totalProductFee+getRet[i].totalDesignFee)/totalFeeWithoutMail;
                                    getRet[i].couponFee = Math.round(orgOrderInfo.coupon_fee*r);
                                }
                            }

                            // 5.按合作方分组创建新订单
                            var asyncFuncs = [];
                            for(var i=0; i<getRet.length; i++) {
                                asyncFuncs.push((function (index, pInfo) {
                                    return function (asyncCallback) {
                                        // 创建分割订单
                                        payUtil.createSplitOrder_v5_5(orgOrderInfo, pInfo,
                                            function(crtErr, crtRet){
                                                asyncCallback(crtErr, crtRet);
                                            }
                                        );
                                    }
                                })(i, getRet[i])); // 利用闭包解决动态参数传递问题
                            }
                            async.series(asyncFuncs, function (error, results){
                                if(error) {
                                    console.log('payUtil.js [splitTradeOrder_v5_5] Loop createSplitOrder_v5_5 Err: ', error);
                                    return callback(error, null);
                                }
                                return callback(null, null);
                            });
                        });

                    } else {
                        console.log('payUtil.js [splitTradeOrder_v5_5] Did not find OrgOrderDetail');
                        return callback('未找到子订单', null);
                    }
                });

            } else {
                console.log('payUtil.js [splitTradeOrder_v5_5] Did not find OrgOrder');
                return callback('无效订单', null);
            }
        });
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 创建分割的订单
     * @param orgOrderInfo 原订单信息(支付订单)
     * @param pInfo 原子订单信息(同一合作方)
     *  {
     *      pId: 123,               // 合作方id
     *      totalProductFee: 300,   // 该合作方分组内所有商品的总制作费
     *      totalDesignFee: 200,    // 该合作方分组内所有商品的总设计费
     *      totalMailFee: 100,      // 该合作方分组内所有商品的总邮费
     *      itemList: [],           // 同(返回值1)的结构
     *      couponFee: 0            // 分摊后的优惠
     *  }
     */
    payUtil.createSplitOrder_v5_5 = function(orgOrderInfo, pInfo, callback) {
        // 创建订单编号
        var newOrderNo = payUtil.createOrderNo(orgOrderInfo.device, 10);

        // 商品总数量
        var itemCnt = pInfo.itemList.length;
        for(var i=0; i<pInfo.itemList.length; i++) {
            var goods = pInfo.itemList[i];
            if(goods.assyList) {
                itemCnt += goods.assyList.length;
            }
        }
        // 订单总金额
        var newTotalFee = pInfo.totalProductFee + pInfo.totalDesignFee + pInfo.totalMailFee - pInfo.couponFee;

        // 创建总订单
        var newEntity = new ItbTradeOrderModel({
            order_no: newOrderNo,
            pay_order_no: orgOrderInfo.order_no,// 支付订单号
            detail_cnt: itemCnt,
            device: orgOrderInfo.device,
            state: 11,// 支付成功
            partner_id: (Number(orgOrderInfo.device||'0')==301)?3:pInfo.pId,// 1:紫云, 3:酒单网
            pay_platform: orgOrderInfo.pay_platform,
            total_fee: newTotalFee||0,
            coupon_fee: pInfo.couponFee||0,
            addr_id: orgOrderInfo.addr_id,
            express_type: orgOrderInfo.express_type,// 配送方式: 10预付邮费, 20到付邮费
            user_id: orgOrderInfo.user_id,
            type: 0,// 普通订单
            desc: orgOrderInfo.desc||'',
            update_by: orgOrderInfo.user_id,
            create_time: (new moment(orgOrderInfo.create_time).format('YYYY-MM-DD HH:mm:ss')),// 保持原订单创建时间
        });
        newEntity.insToDB(function(saveErr, newOrderId){
            if(saveErr){
                console.log('payUtil.js [createSplitOrder_v5_5] Create NewOrder Err: '+saveErr);
                return callback(saveErr, null);
            }
            if(!newOrderId){
                console.log('payUtil.js [createSplitOrder_v5_5] Create NewOrder NG');
                return callback('创建分割订单失败', null);
            }

            // 创建子订单
            // 按已分组的主商品循环处理
            var asyncFuncs = [];
            for(var i=0; i<pInfo.itemList.length; i++) {
                asyncFuncs.push((function (index, goodsInfo) {
                    return function (asyncCallback) {
                        // 子订单(主商品)
                        var newSubEntity = new ItbTradeOrderDetailModel({
                            detail_no: index+'_0',
                            order_id: newOrderId,
                            partner_id: newEntity.partner_id,
                            item_id: goodsInfo.item_id,
                            pp_id: goodsInfo.pp_id,
                            unit: goodsInfo.unit,
                            qty: goodsInfo.qty,
                            user_doc_id: goodsInfo.user_doc_id,
                            fee: goodsInfo.fee,
                            product_fee: goodsInfo.product_fee,
                            design_fee: goodsInfo.design_fee,
                            mail_fee: goodsInfo.mail_fee,
                            update_by: orgOrderInfo.user_id
                        });
                        // 创建子订单
                        newSubEntity.saveToDB(function(err, newOrderDetailId){
                            if(err) {
                                console.log('payUtil.js [createSplitOrder_v5_5] Create NewOrderDetail Err: '+err);
                                return asyncCallback(err, null);
                            }
                            if(!newOrderDetailId) {
                                console.log('payUtil.js [createSplitOrder_v5_5] Create NewOrderDetail NG');
                                return asyncCallback('创建子订单失败', null);
                            }

                            if(goodsInfo.assyList && goodsInfo.assyList.length>0) {
                                // 循环处理配件
                                var asyncFuncs2 = [];
                                for(var j=0; j<goodsInfo.assyList.length; j++){
                                    asyncFuncs2.push((function (index2, assyInfo) {
                                        return function (asyncCallback2) {
                                            // 子订单(配件)
                                            var newAssyEntity = new ItbTradeOrderDetailModel({
                                                base_detail_id: newOrderDetailId,
                                                detail_no: index+'_'+Number(index2+1),
                                                order_id: newOrderId,
                                                partner_id: newEntity.partner_id,
                                                item_id: assyInfo.item_id,
                                                pp_id: assyInfo.pp_id,
                                                unit: assyInfo.unit,
                                                qty: assyInfo.qty,
                                                //user_doc_id: null,
                                                fee: assyInfo.fee,
                                                product_fee: assyInfo.product_fee,
                                                design_fee: assyInfo.design_fee,
                                                mail_fee: assyInfo.mail_fee,
                                                update_by: orgOrderInfo.user_id
                                            });
                                            // 创建子订单
                                            newAssyEntity.saveToDB(function(err2, newOrderDetailId2){
                                                if(err2) {
                                                    console.log('payUtil.js [createSplitOrder_v5_5] Create NewOrderDetail(Assy) Err: '+err2);
                                                }
                                                return asyncCallback2(err2, newOrderDetailId2);
                                            });
                                        }
                                    })(j, goodsInfo.assyList[j])); // 利用闭包解决动态参数传递问题
                                }
                                async.series(asyncFuncs2, function (error2, results2){
                                    if(error2) {
                                        console.log('payUtil.js [createSplitOrder_v5_5] Loop Assy Err: '+error2);
                                    }
                                    // 配件处理返回
                                    return asyncCallback(error2, newOrderDetailId);
                                });
                            } else {
                                return asyncCallback(null, newOrderDetailId);
                            }
                        });
                    }
                })(i, pInfo.itemList[i])); // 利用闭包解决动态参数传递问题
            }
            async.series(asyncFuncs, function (error, results){
                if(error) {
                    console.log('payUtil.js [createSplitOrder_v5_5] Loop Goods Err: '+error);
                    return callback(error, null);
                }

                // 拷贝订单状态变更记录
                (new ItbTradeStateHisModel).copyItemOrderHis(orgOrderInfo.order_id, newOrderId, newTotalFee,
                    function(cpErr, cpRet){
                        if(cpErr) {
                            console.log('payUtil.js [createSplitOrder_v5_5] copyItemOrderHis Err: '+cpErr);
                        }
                        return callback(cpErr, {
                            orderId: newOrderId,
                            orderNo: newOrderNo
                        });
                });
            });
        });
    };

    //--------------------------------------------------------------------------------------------
    // 根据vip订单更新vip会员信息
    // TODO 判断逻辑不严谨
    payUtil.updVipExpiryInfo=function(userId, tradeOrderId, callback){
        // 查找订单信息
        var odrEnt = new ItbTradeOrderDetailModel;
        odrEnt.getDetailOrderInfoByOrderId(tradeOrderId, function(getErr, getRet){
            if(getErr){
                return callback(getErr, null);
            }
            if(getRet && getRet.length>0) {
                var dtlInfo = getRet[0];
                if(dtlInfo.item_type == 9) {
                    // 查找会员信息
                    var mbEnt = new ItbMemberModel;
                    mbEnt.findVipMember(userId, function(findErr, memberInfo) {
                        if(findErr) {
                            return callback(findErr, null);
                        }

                        mbEnt.getTimeFromDB(function(getErr, dbTime){
                            // 新的有效期开始时间
                            var stTime = dbTime.str_sysdate;// 默认重新计算有效期

                            if(memberInfo) {// 已存在会员信息
                                if(memberInfo.validFlg==1) {
                                    // 有效期内: 延长有效期
                                    stTime = memberInfo.str_expiry_time;
                                }
                            }
                            // 更新vip订单商品有效期
                            odrEnt.updVipOdrExpTime(dtlInfo.detailOrderId, userId, stTime, function(updErr){
                                if(updErr){
                                    return callback(updErr, null);
                                }

                                if(memberInfo) {
                                    // 更新会员信息
                                    mbEnt.updVipMemberExpTime2(memberInfo.member_id, userId, stTime, dtlInfo.qty,
                                        function(updErr2){
                                        return callback(updErr2, null);
                                    });

                                } else {
                                    // 新建会员信息
                                    mbEnt.createVipMember(userId, stTime, dtlInfo.qty,
                                        function(crtErr, newMbId){
                                        return callback(crtErr, null);
                                    });
                                }
                            });
                        });
                    });

                } else {
                    return callback(null, null);
                }

            } else {
                return callback(null, null);
            }
        });
    };

    //--------------------------------------------------------------------------------------------
    /**
     * 创建秒杀商品的(真正)商品订单
     * @param skOrderId 原始秒杀订单id
     */
    payUtil.createSeckillRealItemOrder_v6_1 = function(userId, skOrderId, callback) {

        // 根据原始秒杀订单获取商品基本信息
        (new ItbTradeOrderModel).getSeckillOrderItemInfo(skOrderId, function(getErr, odrItemInfo){
            if(getErr) {
                console.log('payUtil.js [createSeckillRealItemOrder_v6_1] Find OrgSkOrder Err: ', getErr);
                return callback(getErr, null);
            }

            if(odrItemInfo) {
                // 创建默认用户文档
                payUtil.crtDefUserDocByDesign(odrItemInfo.user_id, odrItemInfo.design_id, 2/*文档用途*/, function(err, newUserDocId){
                    if(err){
                        // TODO
                        console.log('payUtil.js [createSeckillRealItemOrder_v6_1] Create DefUserDoc Err: ', err);
                    }

                    // 创建商品订单编号
                    var newOrderNo = payUtil.createOrderNo(odrItemInfo.device, 10);

                    // 创建总订单
                    var newEntity = new ItbTradeOrderModel({
                        order_no: newOrderNo,
                        pay_order_no: odrItemInfo.order_no,// 原秒杀订单号
                        detail_cnt: 1,// TODO 暂时只有一个子订单
                        device: odrItemInfo.device,
                        state: 11,// 支付成功
                        partner_id: 100,// 100:示界港
                        pay_platform: odrItemInfo.pay_platform,
                        total_fee: odrItemInfo.total_fee||0,
                        coupon_fee: odrItemInfo.coupon_fee||0,
                        addr_id: odrItemInfo.addr_id,
                        user_id: odrItemInfo.user_id,
                        type: 0,// 普通订单
                        desc: odrItemInfo.desc||'',
                        update_by: odrItemInfo.user_id,
                        create_time: (new moment(odrItemInfo.create_time).format('YYYY-MM-DD HH:mm:ss')),// 保持原秒杀订单创建时间
                    });
                    newEntity.insToDB(function(saveErr, newOrderId){
                        if(saveErr){
                            console.log('payUtil.js [createSeckillRealItemOrder_v6_1] Create NewItemOrder Err: '+saveErr);
                            return callback(saveErr, null);
                        }
                        if(!newOrderId){
                            console.log('payUtil.js [createSeckillRealItemOrder_v6_1] Create NewItemOrder NG');
                            return callback('创建秒杀商品订单失败', null);
                        }

                        // 创建子订单
                        var newSubEntity = new ItbTradeOrderDetailModel({
                            detail_no: '0',
                            order_id: newOrderId,
                            partner_id: newEntity.partner_id,
                            item_id: odrItemInfo.item_id,
                            pp_id: odrItemInfo.pp_id,
                            unit: odrItemInfo.item_unit,
                            qty: odrItemInfo.item_qty,
                            user_doc_id: newUserDocId||null,// 默认用户文档
                            fee: odrItemInfo.detail_fee||0,
                            product_fee: odrItemInfo.detail_prod_fee||0,
                            design_fee: odrItemInfo.detail_design_fee||0,
                            mail_fee: odrItemInfo.detail_mail_fee||0,
                            update_by: odrItemInfo.user_id
                        });
                        // 创建子订单
                        newSubEntity.saveToDB(function(err, newOrderDetailId){
                            if(err) {
                                console.log('payUtil.js [createSeckillRealItemOrder_v6_1] Create NewOrderDetail Err: '+err);
                                return callback(err, null);
                            }
                            if(!newOrderDetailId) {
                                console.log('payUtil.js [createSeckillRealItemOrder_v6_1] Create NewOrderDetail NG');
                                return callback('创建秒杀商品子订单失败', null);
                            }

                            // 拷贝订单状态变更记录
                            (new ItbTradeStateHisModel).copyItemOrderHis(odrItemInfo.order_id, newOrderId, odrItemInfo.total_fee,
                                function(cpErr, cpRet){
                                    if(cpErr) {
                                        console.log('payUtil.js [createSeckillRealItemOrder_v6_1] copyItemOrderHis Err: '+cpErr);
                                    }

                                    // 更新秒杀商品数量(-1)
                                    (new ItbActivityRModel).decrActItemRestQty(odrItemInfo.r_id, odrItemInfo.user_id, function(updErr){

                                        return callback(updErr, {
                                                orderId: newOrderId,
                                                orderNo: newOrderNo,
                                                itemId: odrItemInfo.item_id,
                                                designId: odrItemInfo.design_id,
                                                userDocId: newUserDocId
                                        });
                                    });
                                }
                            );
                        });
                    });
                });

            } else {
                console.log('payUtil.js [createSeckillRealItemOrder_v6_1] Did not find OrgSkOrder');
                return callback('无效订单', null);
            }
        });
    };

    // 根据设计模版创建默认用户文档
    payUtil.crtDefUserDocByDesign = function(userId, designId, purpose, callback){
        if(Number(userId||'0')>0 && Number(designId||'0')>0) {
            (new TgUserDocModel).create_user_doc(designId, userId, Number(purpose||'0'), function(err, newDocId){
                return callback(err, newDocId);
            });
        } else {
            return callback(null, null);
        }
    };

    // 更新锁定商品状态
    //payUtil.updLockActItemSuccess = function(rId, userId, callback){
    //    var url = CONFIG.API_SERVER_IP +':'+CONFIG.API_SERVER_PORT+'/lua/updLockActItemSuccess';
    //
    //    //console.time('---> [payUtil][updLockActItemSuccess]');
    //    // 调用api服务
    //    superagent.post(url)
    //        .send({rId:rId, uId:userId})
    //        .end(function (err, res) {
    //            if (res && res.text) {
    //                console.log('---> [updLockActItemSuccess] Ret: ' + res.text);
    //                var retJson = JSON.parse(res.text);
    //                if(retJson.success==1) {
    //                    return callback(null, retJson.data);
    //                }
    //                return callback(err||'NG', null);
    //            } else {
    //                console.log('---> [updLockActItemSuccess] NG');
    //                return callback(err||'NG', null);
    //            }
    //        }
    //    );
    //};

    /**
     * 检测支付宝支付回调
     *
     * @author 王俊
     * @date 2018-04-18
     *
     * @param {Object} response 阿里响应报文
     * @param {Function} callback 回调
     *                      err: 失败原因
     */
    payUtil.chkAlipayNotify = function (response, callback) {

        var valid = yjscAlipayClient.signVerify(response);
        if (!valid) {
            return callback('验签失败');
        }
        /**
         * https://docs.open.alipay.com/204/105301/
         *
         * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
         * 2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
         * 3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email），
         * 4、验证app_id是否为该商户本身。
         *
         * 上述1、2、3、4有任何一个验证不通过，则表明本次通知是异常通知，务必忽略。
         * 在上述验证通过后商户必须根据支付宝不同类型的业务通知，正确的进行不同的业务处理，并且过滤重复的通知结果数据。
         * 在支付宝的业务通知中，只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时，支付宝才会认定为买家付款成功。
         *
         * */

        /**
         WAIT_BUYER_PAY	交易创建，等待买家付款
         TRADE_CLOSED	未付款交易超时关闭，或支付完成后全额退款
         TRADE_SUCCESS	交易支付成功
         TRADE_FINISHED	交易结束，不可退款

         状态TRADE_SUCCESS的通知触发条件是商户签约的产品支持退款功能的前提下，买家付款成功；
         交易状态TRADE_FINISHED的通知触发条件是商户签约的产品不支持退款功能的前提下，买家付款成功；或者，商户签约的产品支持退款功能的前提下，交易已经成功并且已经超过可退款期限。
         * */

        var totalTasks = [];
        // 1.状态获取
        totalTasks.push(function (callback) {
            var data = {};
            data.aliRes = response;
            var trade_status = response.trade_status;
            if(trade_status === 'TRADE_SUCCESS' || trade_status === 'TRADE_FINISHED') {
                data.tradeState = 11;   // 支付成功
            } else {
                data.tradeState = 12;   // 支付失败
            }
            data.passbackParams = JSON.parse(response.passback_params || '{}');
            return callback(null, data);
        });

        // 2.查询是否已存在记录
        totalTasks.push(function (data, callback) {
            // 检查纪录是否已存在
            var chkEnt = new ItbPaymentHisModel({
                trade_obj_no: response.out_trade_no,
                state: data.tradeState,
                del_flg:0
            });
            chkEnt.findFromDB(function(chkErr, historys){
                if(chkErr) {
                    console.log("payUtil.js [chkWxPayNotifyProc] find Err: "+chkErr);
                }
                if(!historys || historys.length <=0) {
                    data.needInsert = true;     // 标记需要插入历史记录
                }
                return callback(null, data);
            });
        });
        // 3. 按需插入支付历史
        totalTasks.push(function (data, callback) {
            // 支付保回传公共参数, 创建订单时携带
            data.passback = JSON.parse(response.passback_params || '{}');
            if(!data.needInsert) return callback(null, data);
            // 添加支付历史纪录
            var insEnt = new ItbPaymentHisModel({
                type: data.passback.type||0, // 订单类型
                trade_obj_id: data.passback.id||0,
                trade_obj_no: response.out_trade_no||0,
                state: data.tradeState,
                pay_platform: 20, // 支付宝
                desc: 'SUCCESS',
                pay_info1: response.trade_status||'',
                pay_info2: response.sign||'',
                pay_info3: response.notify_time||'',
                pay_info4: response.notify_type||'',
                pay_info5: response.notify_id||'',
                pay_info6: response.app_id||'',
                pay_info7: response.charset||'',
                pay_info8: response.version||'',
                pay_info9: response.sign_type||'',
                pay_info10: response.trade_no||'',
                pay_info11: response.out_trade_no||'',
                pay_info12: response.out_biz_no||'',
                pay_info13: response.buyer_id||'',
                pay_info14: response.buyer_logon_id||'',
                pay_info15: response.seller_id||'',
                pay_info16: response.seller_email||'',
                pay_info17: response.total_amount||0,
                pay_info18: response.receipt_amount||0,
                pay_info19: response.invoice_amount||0,
                pay_info20: response.buyer_pay_amount||0,
                pay_info21: response.point_amount||0,
                pay_info22: response.refund_fee||0,
                pay_info23: response.subject||'',
                pay_info24: response.body||'',
                pay_info25: response.gmt_create||'',
                pay_info26: response.gmt_payment||'',
                pay_info27: response.gmt_refund||'',
                pay_info28: response.gmt_close||'',
                pay_info29: response.fund_bill_list||'',
                pay_info30: response.passback_params||'',
                pay_info31: response.voucher_detail_list||'',
                update_by: data.passback.uid||0
            });

            insEnt.saveToDB(function(insErr, newHisId){
                if(insErr) {
                    console.log("payUtil.js [chkWxPayNotifyProc] Ins PayHis Err: "+insErr);
                }
                return callback(null, data);
            });
        });

        // 4. 订单后续流程
        totalTasks.push(function (data, callback) {
            // 统一后续处理
            var param = {
                userId: data.passback.uid,
                tradeType: data.passback.type,
                tradeObjId: data.passback.id,
                tradeState: data.tradeState,
                totalFee: response.total_amount * 100 // 元 转 分
            };
            payUtil.payNotifyProcCore(param, function(procErr, procRet){
                if (procErr) {
                    console.log("payUtil.js [chkWxPayNotifyProc] payNotifyProcCore Err: "+procErr);
                }
                return callback(procErr, procRet);
            });
        });

        async.waterfall(totalTasks, function (error, data) {
            return callback(error);
        })
    };


    //--------------------------------------------------------------------------------------------
    return payUtil;
})();

//--------------------------------------------------------------------------------------------
module.exports = payUtil;

